﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ShprossesBuilder.Modelling.Components;
using System.Drawing;
using ITAP.Core.Modelling.Primitives;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.Core.Modelling;
using ITAP.Core.Calculations;

namespace ITAP.ShprossesBuilder.Modelling.Measurement
{
    public enum DimensionSide
    {
        Right, 
        Up, 
        Left,
        Down, 
        Auto,
        None
    }

    public class DimensionFactory
    {
        public static Line GetSideLine(RectangleF modelRectangle, DimensionSide side)
        {
            Line sideLine = null;
            switch (side)
            {
                case DimensionSide.Right:
                    sideLine = new Line(new ModelPoint(modelRectangle.X + modelRectangle.Width, modelRectangle.Y),
                                        new ModelPoint(modelRectangle.X + modelRectangle.Width, modelRectangle.Y + modelRectangle.Height));
                    break;
                case DimensionSide.Up:
                    sideLine = new Line(new ModelPoint(modelRectangle.X + modelRectangle.Width, modelRectangle.Y + modelRectangle.Height),
                                        new ModelPoint(modelRectangle.X, modelRectangle.Y + modelRectangle.Height));
                    break;
                case DimensionSide.Left:
                    sideLine = new Line(new ModelPoint(modelRectangle.X, modelRectangle.Y + modelRectangle.Height),
                                        new ModelPoint(modelRectangle.X, modelRectangle.Y));
                    break;
                case DimensionSide.Down:
                    sideLine = new Line(new ModelPoint(modelRectangle.X, modelRectangle.Y),
                                        new ModelPoint(modelRectangle.X + modelRectangle.Width, modelRectangle.Y));
                    break;
            }
            return sideLine;
        }

        public static Dimension CreateSpacerElementLineDimension(SpacerElement spacerElement, RectangleF modelRectangle, DimensionSide side, DimensionType type)
        {            
            
            IWidePrimitive primitive = spacerElement.Primitives[0] as IWidePrimitive;
            SizeDimension dimension = null;
            ModelPoint startPoint = null;
            ModelPoint endPoint = null;
            Line sideLine = DimensionFactory.GetSideLine(modelRectangle, side);
            RectangleF boundingBox;
            if (type == DimensionType.InnerDimension)
            {
             //   boundingBox = primitive.UpBorder.BoundingBox;

                startPoint = sideLine.GetProjectionPoint(primitive.UpBorder.StartPoint);
                endPoint = sideLine.GetProjectionPoint(primitive.UpBorder.EndPoint);

                dimension = new SizeDimension(new Line(startPoint, endPoint), primitive.UpBorder.StartPoint, primitive.UpBorder.EndPoint);
            }
            else
            {
               // boundingBox = primitive.DownBorder.BoundingBox;

                startPoint = sideLine.GetProjectionPoint(primitive.DownBorder.StartPoint);
                endPoint = sideLine.GetProjectionPoint(primitive.DownBorder.EndPoint);
                dimension = new SizeDimension(new Line(startPoint, endPoint), primitive.DownBorder.StartPoint, primitive.DownBorder.EndPoint);
            }
            
            dimension.Side = side;
            return dimension;
        }

        public static Dimension CreateShprossLineDimension(Shpross shpross, RectangleF modelRectangle, DimensionSide side)
        {
            IWidePrimitive primitive = shpross.Primitives[0] as IWidePrimitive;
            //IEndedPrimitive primitive = shpross.Primitives[0] as IEndedPrimitive;
            SizeDimension dimension = null;
            ModelPoint startPoint = null;
            ModelPoint endPoint = null;
            RectangleF boundingBox = primitive.CenterBorder.BoundingBox;
            Line sideLine = DimensionFactory.GetSideLine(modelRectangle, side);

            ModelPoint leftDown = new ModelPoint(boundingBox.X, boundingBox.Y);
            ModelPoint upRight = new ModelPoint(boundingBox.X + boundingBox.Width, boundingBox.Y + boundingBox.Height);

            startPoint = sideLine.GetNearestPrimitivePoint(leftDown);
            endPoint = sideLine.GetNearestPrimitivePoint(upRight);

            dimension = new SizeDimension(new Line(startPoint, endPoint));
            if (SimpleEqualProvider.IsEqual(startPoint, endPoint, 0.000001))
                return null;

            Angle angle = ModelCalculations.GetAngleBetweenVectors(dimension.Primitive.GetNormalLine(0.5), sideLine.GetNormalLine(0.5), true);
            if (angle.Value != 0)
            {
                dimension.Primitive = dimension.Primitive.ExchangeEnds();
                ModelPoint oldStartPoint = dimension.InitialStartPoint;
                dimension.InitialStartPoint = dimension.InitialEndPoint;
                dimension.InitialEndPoint = oldStartPoint;                
            }

            dimension.Side = side;
            return dimension;

        }

        public static Dimension CreatePinHoleDimension(SpacerConnector spacerConnector, SpacerElement spacerElement, DimensionType dimensionType, bool considerAsSizeDimension)
        {
            if (spacerElement == null) 
                return null;
            IWidePrimitive spacerElementPrimitive = (IWidePrimitive)spacerElement.Primitives[0];
            double length;
            double outerLength = double.NaN;
            double offset;
            IEndedPrimitive primitive = null;
            ModelPoint downBorderProjPoint = spacerElementPrimitive.DownBorder.GetProjectionPoint(spacerConnector.StartPoint);

            if (downBorderProjPoint == null)
                return null;

            switch(dimensionType)
            {
                case DimensionType.InnerDimension:   
                    length = spacerElementPrimitive.UpBorder.GetPathLengthFromProjectionToStart(spacerConnector.StartPoint);
                    outerLength = spacerElementPrimitive.UpBorder.GetPathLengthFromProjectionToStart(spacerConnector.StartPoint);
                    offset = outerLength / spacerElementPrimitive.UpBorder.Length;
                    primitive = (IEndedPrimitive)spacerElementPrimitive.UpBorder.Clone();
                    break;
                case DimensionType.OuterDimension:
                    length = spacerElementPrimitive.DownBorder.GetPathLengthFromProjectionToStart(spacerConnector.StartPoint);
                    outerLength = length;
                    offset = outerLength / spacerElementPrimitive.DownBorder.Length;
                    primitive = (IEndedPrimitive)spacerElementPrimitive.DownBorder.Clone();                    
                    break;
                default:
                    length = double.NaN;
                    break;
            }

            if (double.IsNaN(length))
                return null;
//            ModelVector spacerElementNormalLine = spacerElementPrimitive.DownBorder.GetNormalLine(offset).Rotate(new Angle(Math.PI));
             

            primitive.SetLength(EndedPrimitivePoints.Start, outerLength);
            if(dimensionType == DimensionType.InnerDimension)
                primitive = (IEndedPrimitive)primitive.GetOffsetPrimitive(spacerElement.Width);

            //Line line = new Line(spacerElementPrimitive.DownBorder.StartPoint, downBorderProjPoint);
            PinHolesDimension dimension = new PinHolesDimension(primitive, length.ToString("0.0"));
            dimension.Side = DimensionSide.Auto;
            dimension.ConsiderAsSizeDimension = considerAsSizeDimension;
            return dimension;
        }
    }
}
